# coding:utf-8
'''
编写人：zhaogq
时间：2024-10-15
该模块需要安装
pip install pymssql==2.2.7
'''
import pymssql
import datetime
import decimal
from typing import Dict

# 映射数据对象
def mapData(data: Dict, fields: Dict):
    returnData = {}
    for field in fields.keys():
        if fields[field] in data:
            returnData[field] = data[fields[field]]
    return returnData

class ZgqMssql():
    '''构造函数'''
    db = None
    def __init__(self, dbConfig):
        host = dbConfig['host'] # 数据库连接地址
        port = dbConfig['port']  # 数据库连接端口
        user = dbConfig['user']  # 用户名
        passwd = dbConfig['passwd']  # 密码
        db = dbConfig['db']  # 数据库名
        charset = dbConfig['charset']  # 数据库连接编码
        # 打开数据库连接
        self.db = pymssql.connect(host,user,passwd, db)

    # 格式化类型
    def __f(self, data, value):
        retData = None
        if type(value) in (datetime.datetime, datetime.date, datetime.timedelta):
            retData = str(value)  # 判断是否日期时间类型
        elif type(value) in [decimal.Decimal]:
            retData = float(value)
        elif type(value) is bytes:
            retData = value.decode()
        else:
            retData = value
        return retData

    # 关闭数库库
    def close(self):
        self.db.close()

    # 提交事务
    def commit(self):
        self.db.commit()

    # 回滚事务
    def rollback(self):
        self.db.rollback()

    # 执行自定义查询
    def query(self, sql=''):
        cursor = self.db.cursor()       # 使用 cursor() 方法创建一个游标对象 cursor
        cursor.execute(sql)             # 执行SQL
        fields = [field[0] for field in cursor.description] # 字段名称
        dataList = []                   # 需要返回的数据
        for sdata in cursor.fetchall():
            dataValue = {}              # 单行数据
            for ind, value in enumerate(sdata):
                dataValue[fields[ind]] = self.__f(sdata, value) # 赋值前格式化返回的类型
            dataList.append(dataValue)
        return dataList
    
    # 执行自定义SQL
    def execute(self, sql):
        cursor = self.db.cursor()       # 使用 cursor() 方法创建一个游标对象 cursor
        cursor.execute(sql)             # 执行SQL
        return cursor.rowcount          # 返回影响行数
        
    # 插入一条或多条数据
    def add(self, tableName: object, addData: object, way: object = 'insert', getsql: object = False) -> object:
        if not addData:
            return 0
        way = way.lower()
        if (type(addData) == dict ):  # 单条数据写入
            insertData = [addData]
        elif(type(addData) == list ):  # 多条数据写入
            insertData = addData

        if len(insertData) == 0:
            return 0

        fields = []  # 字段
        valuess = []  # 数据
        for inx, insertInfo in enumerate(insertData):  # 循环待写入数据
            values = []  # 单次数据
            for field, value in insertInfo.items():
                if ( inx == 0 ):
                    fields.append(field)  # 循环第一次才组装字段列表
                if (type(value) in (int,float)):  # 判断是否为整数类型或浮点数
                    values.append(str(value))  # 转为字符串
                elif (value is None):  # 判断是否为None
                    values.append('NULL')
                else:  # 其它情况
                    value = str(value)
                    value = value.replace('\\','\\\\').replace('"','\\"')
                    values.append('\'{}\''.format(value))
            valuess.append('({})'.format(','.join(values)))

        insertSql = '{} into {} ({}) values {}'.format(way,tableName,','.join(fields),','.join(valuess))

        if getsql:
            return insertSql
        else:
            ret = self.execute(insertSql)  # 执行语句并获取影响行数
            return ret  # 返回影响行数

    #  更新数据
    def update(self, tableName, data, where, getsql=False):
        updateSetList = []
        for field, value in data.items():
            if (type(value) == int):  # 判断是否为整数类型或浮点数
                valueStr = str(value)
            elif (value is None):  # 判断是否为None
                valueStr = 'NULL'
            elif (type(value) == float):  # 判断是否为float

                valueStr = str(value)
            else:  # 其它情况
                valueStr = '\'{}\''.format(str(value).replace('\\', '\\\\').replace('"', '\\"'))

            updateSetList.append('{} = {}'.format(field,valueStr))

        updateSetStr = ' , '.join(updateSetList)
        # updateSql = 'update ' + tableName + ' set ' + updateSetStr + ' where ' + where + ''
        updateSql = 'update {} set {} where {}'.format(tableName, updateSetStr, where)

        if getsql:
            return updateSql
        else:
            ret = self.execute(updateSql)  # 执行语句并获取影响行数
            return ret  # 返回影响行数

    #查询一个字段
    def getOne(self,sql='',cache_time=0):
        cursor = self.db.cursor()  # 使用cursor()方法获取操作游标
        cursor.execute(sql)  # 使用execute方法执行SQL语句
        data = cursor.fetchone()  # 使用 fetchone() 方法获取一条数据
        retData = self.__f(data, data[0]) # 只取第一个字段
        return retData  # 返回一条记录的dict
        
    # 查询一行记录，返回字典
    def getRow(self,sql=''):
        cursor = self.db.cursor()  # 使用cursor()方法获取操作游标
        cursor.execute(sql)  # 使用execute方法执行SQL语句
        data = cursor.fetchone()  # 使用 fetchone() 方法获取一条数据
        rowInfo = {}
        for ind,field in enumerate(cursor.description):  # 循环字段名称
            rowInfo[field[0]] = self.__f(data, data[ind])
        return rowInfo  # 返回数据，最后一次插入的id        
    
    # end